AWS Advanced NodeJS Wrapperを使ってRDS Postgresに接続してみた

AWS Advanced NodeJS Wrapperを使ってRDS Postgresに接続してみた

Clock Icon2024.12.26

リテールアプリ共創部@大阪の岩田です。少し前ですが2024/11/20付けのアップデートでAWS Advanced NodeJS DriverがGAしていました。

https://aws.amazon.com/about-aws/whats-new/2024/11/aws-advanced-nodejs-driver/

これまでもJavaでAWS Advanced JDBC Driverが提供されていましたが、これと同様にNode.jsでもRDSに特化したドライバが使えるようになりました。

すでに色々なプラグインが提供されているのですが、取り急ぎ利用頻度の高そうなAWS Secrets Manager PluginAWS IAM Authentication Pluginを使ってEC2からRDS for PostgreSQLへの接続を試してみました。

環境

今回利用した環境は以下の通りです。

  • Amazon Linux 2023
  • Node.js v22.11.0
  • @aws-sdk/client-secrets-manager: 3.716.0
  • @aws-sdk/credential-providers: 3.716.0
  • @aws-sdk/rds-signer: 3.716.0
  • aws-advanced-nodejs-wrapper: 1.1.0
  • pg: 8.13.1

AWS Secrets Manager Pluginを使って接続してみる

まずSecrets Managerから取得した認証情報を使って接続するためのプラグインAWS Secrets Manager Pluginから試してみます。前提としてRDSのクラスタ作成時の「認証情報の管理」に「AWS Secrets Manager で管理」を指定していることとします。

認証情報管理の指定

続いて必要なライブラリをインストールします。

npm install @aws-sdk/client-secrets-manager aws-advanced-nodejs-wrapper pg 

AWS Advanced NodeJS Wrapper本体に加えてAWS Secrets Manager Pluginの依存関係として@aws-sdk/client-secrets-managerの指定も必要です。また、今回はMySQLではなくPostgresを利用しているのでpgもインストールしています。

続いてRDSにTLS接続する際必要なルートCA証明書をダウンロードしておきます。

wget https://truststore.pki.rds.amazonaws.com/ap-northeast-1/ap-northeast-1-bundle.pem

EC2からSecrets Managerにアクセスできるように適切なIAMロールと権限を割り当てます。今回はマネージドポリシーのSecretsManagerReadWriteを割り当てました。

ここまでで準備ができたので、AWS Secrets Manager Pluginのサンプルを参考にJSのコードを実装します。基本的にサンプルそのままでエンドポイント等の情報を調整しつつ、CA証明書を読み込むロジックを追加しています。

secrets-manager.mjs
/*
  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

import { readFileSync } from "fs";
import { AwsPGClient }  from "aws-advanced-nodejs-wrapper/dist/pg/lib/index.js";

const postgresHost = "<RDSのエンドポイント>";
const database = "<RDSのDB名>";
const port = 5432;
const secretId = "<Secrets Managerのシークレット名>";
const secretRegion = "ap-northeast-1";
/* secretId can be set as secret ARN instead. The ARN includes the secretRegion */
// const secretId = "arn:aws:secretsmanager:us-east-1:AccountId:secret:SecretName-6RandomCharacters";

const client = new AwsPGClient({
  // Enable the AWS Secrets Manager Connection Plugin and configure connection parameters.
  host: postgresHost,
  database: database,
  port: port,
  secretId: secretId,
  secretRegion: secretRegion,
  plugins: "secretsManager",
  ssl: {
    ca: readFileSync('<CA証明書の保存先パス>').toString()
  }
});

// Attempt connection.
try {
  await client.connect();
  const result = await client.query("select 1");
  console.log(result);
} finally {
  await client.end();
}

準備ができたので実行してみます。

node secrets-manager.mjs

以下のように出力されれば接続成功です!

Result {
  command: 'SELECT',
  rowCount: 1,
  oid: null,
  rows: [ { '?column?': 1 } ],
  fields: [
    Field {
      name: '?column?',
      tableID: 0,
      columnID: 0,
      dataTypeID: 23,
      dataTypeSize: 4,
      dataTypeModifier: -1,
      format: 'text'
    }
  ],
  _parsers: [ [Function: parseInteger] ],
  _types: TypeOverrides {
    _types: {
      getTypeParser: [Function: getTypeParser],
      setTypeParser: [Function: setTypeParser],
      arrayParser: [Object],
      builtins: [Object]
    },
    text: {},
    binary: {}
  },
  RowCtor: null,
  rowAsArray: false,
  _prebuiltEmptyResultObject: { '?column?': null }
}

AWS IAM Authentication Pluginを使って接続してみる

続いてIAM認証を使って接続するためのプラグインAWS IAM Authentication Pluginによる接続も試してみます。前提として事前にRDSの設定でIAM DB 認証が有効化されていることとします。

まずAWS IAM Authentication Pluginの利用に必要なライブラリを追加導入します。

npm install @aws-sdk/credential-providers @aws-sdk/rds-signer

続いてEC2用のIAMロールにrds-db:connectの権限を追加します。今回はインラインポリシーで以下のポリシーを追加しました。

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "VisualEditor0",
			"Effect": "Allow",
			"Action": "rds-db:connect",
			"Resource": "*"
		}
	]
}

最後にRDS接続用のDBユーザーにrds_iamの権限を付与しておきます。

GRANT rds_iam to <RDSのユーザー名>;

これで準備ができたのでJSのコードを実装します。こちらもAWS IAM Authentication Pluginのサンプルを参考に実装しました。

iam.mjs
/*
  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

import { readFileSync } from "fs";
import { AwsPGClient }  from "aws-advanced-nodejs-wrapper/dist/pg/lib/index.js";

const postgresHost = "<RDSのエンドポイント>";
const username = "<RDSのユーザー名>";
const database = "<RDSのDB名>";
const port = 5432;

const client = new AwsPGClient({
  // Enable AWS IAM database authentication and configure connection parameters
  host: postgresHost,
  port: port,
  user: username,
  plugins: "iam",
  iamRegion: "ap-northeast-1",
  database: database,
  ssl: {
    ca: readFileSync("<CA証明書の保存先パス>").toString()
  }
});

// Attempt connection
try {
  await client.connect();
  const result = await client.query("select now()");
  console.log(result);
} finally {
  await client.end();
}

準備ができたので実行してみます。

node iam.mjs

以下のように出力されれば接続成功です!

Result {
  command: 'SELECT',
  rowCount: 1,
  oid: null,
  rows: [ { now: 2024-12-26T02:21:07.908Z } ],
  fields: [
    Field {
      name: 'now',
      tableID: 0,
      columnID: 0,
      dataTypeID: 1184,
      dataTypeSize: 8,
      dataTypeModifier: -1,
      format: 'text'
    }
  ],
  _parsers: [ [Function: parseDate] ],
  _types: TypeOverrides {
    _types: {
      getTypeParser: [Function: getTypeParser],
      setTypeParser: [Function: setTypeParser],
      arrayParser: [Object],
      builtins: [Object]
    },
    text: {},
    binary: {}
  },
  RowCtor: null,
  rowAsArray: false,
  _prebuiltEmptyResultObject: { now: null }
}

まとめ

簡単にですがAWS Advanced NodeJS Wrapperを試してみました。通常のドライバと比べてAWSやRDSに特化した最適化や便利機能が利用できるため、今後Node.js案件では積極的に活用していきたいですね。今後DSQL向けのプラグインが出てくることにも期待したいです。

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.